package com.github.llyb120.dsl

abstract class AbstractDslMaker {

    private final LinkedList<Object> stack = new LinkedList<>();

    final protected DslParser parser(Closure closure){
        DslParser parser = new DslParser();
        stack.addLast(parser);
        closure.call();
        try{
            return parser;
        } finally {
            stack.removeLast();
        }
    }

    final protected void element(String name, Closure closure){
        def item = stack.getLast();
        assert item instanceof DslParser;
        DslElement element = new DslElement();
        element.setName(name);
        item.elementList.add(element);
        stack.addLast(element);
        closure.call();
        stack.removeLast();
    }

    final protected void element(Closure closure){
        def item = stack.getLast();
        assert item instanceof DslParser;
        DslElement element = new DslElement();
        item.elementList.add(element);
        stack.addLast(element);
        closure.call();
        stack.removeLast();
    }

    final protected void root(boolean flag){
        def item = stack.getLast()
        assert item instanceof DslElement
        item.setRoot(flag)
    }

    final protected void constructor(String... properties){
        def item = stack.getLast()
        assert item instanceof DslElement
        item.getConstructors().add(properties)
    }

    final protected DslProperty property(String name){
        def item = stack.getLast();
        assert item instanceof DslElement;
        DslProperty child = new DslProperty();
        child.setName(name)
        item.getPropertyList().add(child);
        return child
    }

    final protected void property(String name, Closure closure){
        def child = property(name)
//        def item = stack.getLast();
//        assert item instanceof DslElement;
//        DslProperty child = new DslProperty();
//        child.setName(name)
//        item.getPropertyList().add(child);
        stack.addLast(child);
        closure.call();
        stack.removeLast();
    }

    final protected void property(Closure closure){
        def item = stack.getLast();
        assert item instanceof DslElement;
        DslProperty child = new DslProperty();
        item.getPropertyList().add(child);
        stack.addLast(child);
        closure.call();
        stack.removeLast();
    }

    final protected void name(String name){
        def item = stack.getLast();
        if(item instanceof DslProperty){
            item.setName(name);
            return;
        }
        if(item instanceof DslElement){
            item.setName(name);
            return;
        }
        assert false;
    }

    final protected void type(Class type){
        def item = stack.getLast();
        if(item instanceof DslProperty){
            item.setType(type)
            return;
        }
        assert false;
    }

    final protected void multiple(boolean flag){
        def item = stack.getLast();
        if(item instanceof DslProperty){
            item.setMultiple(flag);
            return;
        }
        assert false;
    }


    abstract protected DslParser createParser();

    void generate(String path, String packageName){
        createParser().generate(path, packageName)
    }


}
